package com.appengine.utils;

import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;

import android.app.ProgressDialog;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import com.datatypes.AEuser;
import com.datatypes.Activity;
import com.datatypes.FriendsZone;
import com.datatypes.OfflineLogs;
import com.datatypes.Track;
import com.datatypes.User;
import com.google.gson.Gson;
import com.sporteamws.SharedPref;

public class UserUtils {
	/* --- global variables --- */
	private static String SporTeamURL = "http://sporteamws.appspot.com/";
	private static String GsonServlet = "GSONcom";
	private static String GetUserInfo = "GetUserInfo";
	private static String UpdateUserServlet = "UpdateUser";

	private static AEuser GetAEuserInfo(String facebookid, Context c) {
		JSONObject json = null;
		AEuser ae_user = null;
		long lastUpdatedTrack = SavingAndLoadingCenter.loadLastUpdatedTrack(c);
		
		try {
			String reqURL = SporTeamURL + GsonServlet + "?facebookid="
					+ facebookid;

			/* new sync -- efficient and clean 
			reqURL = SporTeamURL + GetUserInfo + "?request_type=get_user_for_sync" + "&facebook_ID="
					+ facebookid + "&last_updated_track=" + lastUpdatedTrack; */
			
			
			// read json object from app engine servers
			json = JsonUtils.readJsonFromUrl(reqURL);
			if (json == null)
				throw new Exception();

			/* --- get all essential information from server --- */

			// get user json
			String userStr = (String) json.get("user");

			// get tracks json
			String tracksStr = (String) json.get("tracks");

			// get activities json
			String actsStr = (String) json.get("activities");

			// get sporteam friends json
			String friendsStr = (String) json.get("friends");

			// convert user back from Gson string
			ae_user = GsonUtils.ConvertGsonStringToAEuser(userStr);

			// load tracks
			ae_user.SetTracks(GsonUtils.ConvertGsonStringToTracks(tracksStr));

			// load activities
			ae_user.SetActivities(GsonUtils
					.ConvertGsonStringToActivities(actsStr));

			// load friends
			ae_user.SetFriends(GsonUtils.ConvertGsonStringToFriends(friendsStr));

		} catch (Exception e) {
			SharedPref.GotNetworkConnection = false;
			Log.e("error in sync", e.toString());
			UIUtils.PrintToast(c, "no internet connection", Toast.LENGTH_LONG);

			return null;

		}

		return ae_user;

	}

	// send track to appenigne servers
	public static boolean SendTrack(Track track, String facebook_ID) {

		if (!SharedPref.GotNetworkConnection) {
			return false;
		}

		JSONStringer json = null;
		String UpdateUserURL = SporTeamURL + UpdateUserServlet;

		// convert track to gson string
		Gson gson = new Gson();
		String TrackStr = gson.toJson(track);

		// prepare Json
		try {
			json = new JSONStringer().object().key("update_info")
					.value("track").key("track").value(TrackStr)
					.key("facebook_ID").value(facebook_ID).endObject();

			// send json
			boolean sentJson = JsonUtils.SendJsonStringer(json, UpdateUserURL);
			if (!sentJson)
				return false;

		} catch (JSONException e) {
			Log.e("json exception", e.toString());
			return false;
		} catch (Exception e) {
			Log.e("error", e.toString());
			return false;
		}

		return true;
	}

	// send track to user
	public static boolean SendTrackToUser(Track track, String from_ID,
			String to_ID) {

		JSONStringer json = null;
		String UpdateUserURL = SporTeamURL + UpdateUserServlet;

		// convert track to gson string
		Gson gson = new Gson();
		String TrackStr = gson.toJson(track);

		// prepare Json
		try {
			json = new JSONStringer().object().key("update_info")
					.value("social_track").key("track").value(TrackStr)
					.key("from").value(from_ID).key("to").value(to_ID)
					.endObject();
		} catch (JSONException e) {
			Log.e("json exeption", e.toString());
			return false;
		}

		// send json
		JsonUtils.SendJsonStringer(json, UpdateUserURL);

		return true;
	}

	// delete track from appengine database
	public static boolean DeleteTrack(long trackID, String facebookID) {

		final long f_trackID = trackID;
		final String f_fID = facebookID;

		if (!SharedPref.GotNetworkConnection)
			return false;

		Thread t = new Thread() {
			@Override
			public void run() {
				JSONStringer json = null;
				String UpdateUserURL = SporTeamURL + UpdateUserServlet;
				// prepare Json
				try {
					json = new JSONStringer().object().key("update_info")
							.value("delete_track").key("track_ID")
							.value("" + f_trackID).key("facebook_ID")
							.value(f_fID).endObject();
				} catch (JSONException e) {
					Log.e("json exeption", e.toString());
				}

				// send json
				JsonUtils.SendJsonStringer(json, UpdateUserURL);
			}
		};

		t.start();

		return true;
	}

	public static boolean UpdateTrack(Track track, String facebookID) {
		final Track f_track = track;
		final String f_fID = facebookID;
		if (!SharedPref.GotNetworkConnection)
			return false;

		JSONStringer json = null;
		String UpdateUserURL = SporTeamURL + UpdateUserServlet;

		// convert track to gson string
		Gson gson = new Gson();
		String TrackStr = gson.toJson(f_track);

		// prepare Json
		try {
			json = new JSONStringer().object().key("update_info")
					.value("update_track").key("track").value(TrackStr)
					.key("facebook_ID").value(f_fID).endObject();
		} catch (JSONException e) {
			Log.e("json exeption", e.toString());
			return false;
		}

		// send json
		JsonUtils.SendJsonStringer(json, UpdateUserURL);

		return true;
	}

	public static boolean RenameTrack(String facebookID, long trackID,
			String newName) {

		if (!SharedPref.GotNetworkConnection)
			return false;

		final String f_facebookID = facebookID;
		final long f_trackID = trackID;
		final String f_newName = newName;

		Thread t = new Thread() {
			@Override
			public void run() {
				JSONStringer json = null;
				String UpdateUserURL = SporTeamURL + UpdateUserServlet;
				// prepare Json
				try {
					json = new JSONStringer().object().key("update_info")
							.value("rename_track").key("track_ID")
							.value("" + f_trackID).key("facebook_ID")
							.value(f_facebookID).key("name").value(f_newName)
							.endObject();
				} catch (JSONException e) {
					Log.e("json exeption", e.toString());
				}

				// send json
				JsonUtils.SendJsonStringer(json, UpdateUserURL);
			}
		};

		t.start();

		return true;
	}

	public static boolean UpdateTrackSynced(String facebookID, long trackID,
			boolean synced) {

		if (!SharedPref.GotNetworkConnection)
			return false;

		final String f_facebookID = facebookID;
		final long f_trackID = trackID;
		String IsSynced;

		if (synced)
			IsSynced = "synced";
		else
			IsSynced = "not_synced";
		final String f_IsSynced = IsSynced;

		Thread t = new Thread() {
			@Override
			public void run() {
				JSONStringer json = null;
				String UpdateUserURL = SporTeamURL + UpdateUserServlet;
				// prepare Json
				try {
					json = new JSONStringer().object().key("update_info")
							.value("update_track_synced").key("track_ID")
							.value("" + f_trackID).key("facebook_ID")
							.value(f_facebookID).key("sync_status")
							.value(f_IsSynced).endObject();
				} catch (JSONException e) {
					Log.e("json exeption", e.toString());
				}

				// send json
				JsonUtils.SendJsonStringer(json, UpdateUserURL);
			}
		};

		t.start();

		return true;
	}

	public static boolean UpdateActivitySynced(String facebookID,
			String activityID, boolean synced) {

		if (!SharedPref.GotNetworkConnection)
			return false;

		final String f_facebookID = facebookID;
		final String f_actID = activityID;
		String IsSynced;

		if (synced)
			IsSynced = "synced";
		else
			IsSynced = "not_synced";
		final String f_IsSynced = IsSynced;

		Thread t = new Thread() {
			@Override
			public void run() {
				JSONStringer json = null;
				String UpdateUserURL = SporTeamURL + UpdateUserServlet;
				// prepare Json
				try {
					json = new JSONStringer().object().key("update_info")
							.value("update_activity_synced").key("act_ID")
							.value(f_actID).key("facebook_ID")
							.value(f_facebookID).key("sync_status")
							.value(f_IsSynced).endObject();
				} catch (JSONException e) {
					Log.e("json exeption", e.toString());
				}

				// send json
				JsonUtils.SendJsonStringer(json, UpdateUserURL);
			}
		};

		t.start();

		return true;
	}

	public static boolean UpdateActivityClosed(String facebookID,
			String activityID, boolean closed) {

		if (!SharedPref.GotNetworkConnection)
			return false;

		final String f_facebookID = facebookID;
		final String f_actID = activityID;
		String IsClosed;

		if (closed)
			IsClosed = "closed";
		else
			IsClosed = "open";
		final String f_IsClosed = IsClosed;

		Thread t = new Thread() {
			@Override
			public void run() {
				JSONStringer json = null;
				String UpdateUserURL = SporTeamURL + UpdateUserServlet;

				// prepare Json
				try {
					json = new JSONStringer().object().key("update_info")
							.value("update_activity_closed").key("act_ID")
							.value(f_actID).key("facebook_ID")
							.value(f_facebookID).key("activity_status")
							.value(f_IsClosed).endObject();
				} catch (JSONException e) {
					Log.e("json exeption", e.toString());
				}

				// send json
				JsonUtils.SendJsonStringer(json, UpdateUserURL);
			}
		};

		t.start();

		return true;
	}

	// send track to user
	public static boolean SendActivityToUser(Activity act) {

		if (!SharedPref.GotNetworkConnection)
			return false;

		// convert track to gson string
		JSONStringer json = null;
		Gson gson = new Gson();
		String ActStr = gson.toJson(act);
		String UpdateUserURL = SporTeamURL + UpdateUserServlet;

		// prepare Json
		try {
			json = new JSONStringer().object().key("update_info")
					.value("activity").key("activity").value(ActStr)
					.endObject();

			// send json
			boolean sentJson = JsonUtils.SendJsonStringer(json, UpdateUserURL);
			if (!sentJson)
				return false;

		} catch (JSONException e) {
			Log.e("json exeption", e.toString());
			return false;
		} catch (Exception e) {
			return false;
		}

		return true;

	}

	// sync user data with appengine, recieve the most updated user
	public static boolean SyncUserData(String facebookID, Context c) {

		AEuser ae_user;
		User user;
		User loaded_user = SavingAndLoadingCenter.loadUser(
				SharedPref.facebookID, c);
		if (loaded_user == null) {
			// download user from appengine
			ae_user = GetAEuserInfo(facebookID, c);

			if (ae_user == null)
				return false;
			else
				user = new User(ae_user);
		} else {
			ae_user = GetAEuserInfo(facebookID, c); // TODO tmp
			if (ae_user == null)
				return false;
			else
				user = new User(ae_user);

			HandleLogs(facebookID, c);
		}

		// update internal storage
		CacheUserData(ae_user, user, c);

		return true;
	}

	// caches all esential user information on android internal storage
	public static void CacheUserData(AEuser ae_user, User user, Context c) {

		// save tracks
		SavingAndLoadingCenter.saveUserTracks(user.GetFacebookID(),
				ae_user.GetTracks(), c);

		// save activities
		SavingAndLoadingCenter.saveActivityTracks(user.GetFacebookID(),
				ae_user.GetActivities(), c);

		// save user
		SavingAndLoadingCenter.saveUser(user, c);

		// save friends zone
		if (ae_user.GetSporTeamFriends() == null)
			ae_user.InitSporTeamFriends();

		FriendsZone fz = new FriendsZone(ae_user.GetSporTeamFriends(),
				ae_user.GetActivities());

		SavingAndLoadingCenter.saveFriendsZone(ae_user.GetFacebookID(), fz, c);

	}

	// returns the most updated user from server
	public static User GetMostUpdatedUser(String facebookID, Context c) {
		User user = new User();
		user.SetFacebookID(facebookID);
		SyncUserData(facebookID, c);
		return user;
	}

	public static void HandleLogs(String userId, Context c) {
		try {
			OfflineLogs oll = SavingAndLoadingCenter.loadOfflineLogs(userId, c);
			SavingAndLoadingCenter.deleteLogs(userId, c);
			if (!oll.isEmpety()) {
				oll.logsHandle_activity(c);
				oll.logsHandle_deleteTracks();
				oll.logsHandle_syncTracks(c);
				oll.logsHandle_post(c);
			}
		} catch (Exception e) {
			Log.e("error on handling logs", e.toString());

		}

	}

	
	 
	  
}


 